/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package praticas.projeto.FipAmigos;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import praticas.projeto.beans.Usuario;
import praticas.projeto.exceptions.AmigoRepetidoException;
import praticas.projeto.exceptions.AtributoNaoPreenchidoException;
import praticas.projeto.exceptions.ContaRepetidaException;
import praticas.projeto.exceptions.LoginInvalidoException;
import praticas.projeto.exceptions.SenhaInvalidaException;
import praticas.projeto.exceptions.UsuarioNaoCadastradoException;
import praticas.projeto.persistencia.Persistencia;

/**
 *
 * @author Windows
 */
public class FipAmigos {

    //Criando logger para a classe FipAmigos
    private Logger logger = Logger.getLogger(FipAmigos.class);

    //Criando um Map para a classe Usuario
    private Map<String, Usuario> usuarios;

    //Variavel do tipo Persistencia
    private Persistencia p;

    /*
     *Construtor da classe FipAmigos
     *Configura o propertyConfigurator
    */
    public FipAmigos(){
        this.usuarios  = new HashMap<String, Usuario>();
        PropertyConfigurator.configure("WEB-INF/log4j.properties");
        p = new Persistencia("fipamigos.txt");
     }
     /*
     * Metodo criaUsuario passando login, senha e nome como parametros;
     * Adiciona se o login não for igual a null nem a vazio;
     * Se o usuario ja não está adicionado no sistema;
     * e se a senha for dierente de null ou de vazio e conter acima de 5 caracteres;
     */
    public void criarUsuario(String login, String senha, String nome) throws SenhaInvalidaException, ContaRepetidaException, LoginInvalidoException, IOException {
        logger.info("Criando Usuario com login: "+ login + " Senha: "+ senha + " Nome: "+ nome);
        
        if (login==null || login.equals("")) throw new LoginInvalidoException();
        if (this.contemUsuario(login)) throw new ContaRepetidaException();
        if (senha == null || senha.equals("") || senha.length() <= 5) throw new SenhaInvalidaException();       
        Usuario usuario = new Usuario(login, senha, nome);
        this.usuarios.put(login, usuario);        
        p.gravaArquivo(usuarios);
        
    }

    /*
     * Retorna o nome do usuario do login passado como parametro
     * mas se satisfazer as seguintes condições
     * se o login passado não for null nem vazio
     * ou se o login já estiver cadastrado no sistema!
     */
    public String getNomeUsuario(String login) throws LoginInvalidoException, UsuarioNaoCadastradoException, IOException, ClassNotFoundException {
        logger.info("Retornando o Usuario com login: "+ login);

        if (login == null || login.equals("")) throw new LoginInvalidoException();
        if (!this.contemUsuario(login)) throw new UsuarioNaoCadastradoException();
          
        Map<String, Usuario> users = p.lerArquivo();
        String usuario = users.get(login).getNome();
        return usuario;        
    }

    /*
     * Retorna a descrição de um usuario se somente se a descrição não for nula nem vazia!
     * se for lança uma exceção Atributo não preenchido
     * Retorna a descrição do usuario passando o login e senha e verifica na lista de usuarios!
     */
    public String getDescricao(String login, String senha) throws AtributoNaoPreenchidoException {
        logger.info("Retornando a descrição do Usuario com login: "+ login + " Senha: "+ senha);
        
        Usuario usuario = this.usuarios.get(login);

        if (usuario.getDescricao()==null || usuario.getDescricao().equals("")) {
          throw new AtributoNaoPreenchidoException();
        }

        return usuario.getDescricao();

    }

    /*
     * Retorna o estado civil do usuario, se somente se o estado civil não for nulo nem vazio
     * se for lança uma exceção Atributo não preenchido
     * Retorna o estado civil de um usuario passando o login e a senha como parametros e verifica na lista de usuarios;
     */
    public String getEstadoCivil(String login, String senha) throws AtributoNaoPreenchidoException, SenhaInvalidaException {
        logger.info("Retornando o estado civil do Usuario com login: "+ login + " Senha: "+ senha);

        Usuario usuario = this.usuarios.get(login);

        if (usuario.getEstadoCivil()==null || usuario.getEstadoCivil().equals("")) {
            throw new AtributoNaoPreenchidoException();
        }
      return usuario.getEstadoCivil();
    }
    
    /*
     * Retorna o aniversario do usuario, se somente se o aniversario não for nulo nem vazio;
     * se for lança uma exceção Atributo não preenchido
     * Retorna o aniversario de um usuario passando o login e senha como parametros e verifica na lista de usuarios cadastrados no sistema;
     */
    public String getAniversario(String login, String senha) throws AtributoNaoPreenchidoException, SenhaInvalidaException {
        logger.info("Retornando o Aniversário do Usuario com login: "+ login + " Senha: "+ senha);

        Usuario usuario = this.usuarios.get(login);

        if (usuario.getAniversario()==null || usuario.getAniversario().equals("")) {
            throw new AtributoNaoPreenchidoException();
        }
            return usuario.getAniversario();
    }

    /*
     * Retorna a cidade natal de um ususuario, se somente se a cidade não for nula nem vazia
     * se for lança uma exceção Atributo não preenchido
     * Retorna a cidade natal de um usuario passando como parametro
     * o login e a senha, e verifica na lista de usuarios cadastrados no sistema;
     */
    public String getCidadeNatal(String login, String senha) throws AtributoNaoPreenchidoException, SenhaInvalidaException {
        logger.info("Retornando a Cidade Natal do Usuario com login: "+ login + " Senha: "+ senha);

        Usuario usuario = this.usuarios.get(login);

        if (usuario.getCidadeNatal()==null || usuario.getCidadeNatal().equals("")) {
            throw new AtributoNaoPreenchidoException();
        }
            return usuario.getCidadeNatal();
    }

    /*
     * Metodo que retorna verdadeiro se na lista de usuarios contem o login passado como parametro
     * ou falso se não contiver na lista de ususarios do sistema;
     */
    public boolean contemUsuario(String login) {
        logger.info("Verificando se contem o Usuario com login: "+ login);

        if (this.usuarios.containsKey(login)) {
            return true;
        } else {
            return false;
        }
    }

    /*
     * Metodo para edição da descrição de um usuario, passando como parametro login, senha e a decrição
     * verifica se contem o usuario e se a senha é valida
     * se não for lança duas exceções
     * UsuarioNaoCadastrado e SenhaInvalida
     * Caso contrario edita a decrição
     */
    public void editarDescricao(String login, String senha, String descricao) throws UsuarioNaoCadastradoException, SenhaInvalidaException {
        logger.info("Editando a descrição do Usuario com login: "+ login + " Senha: "+ senha + " Descrição:" +descricao);

        Usuario usuario = this.usuarios.get(login);

        if (!this.contemUsuario(login)) {
            throw new UsuarioNaoCadastradoException();
        }
            if (!senha.equals(usuario.getSenha()))
                throw new SenhaInvalidaException("Senha inválida.");
                usuario.setDescricao(descricao);
        
    }

    /*
     * Metodo para edição do estado civil de um usuario, passando como parametro login, senha e o estado
     * verifica se contem o usuario e se a senha é valida
     * se não for lança duas exceções
     * UsuarioNaoCadastrado e SenhaInvalida
     * Caso contrario edita o estado civil
     */
    public void editarEstadoCivil(String login, String senha, String estado) throws UsuarioNaoCadastradoException, SenhaInvalidaException {
        logger.info("Editando o estado Civil do Usuario com login: "+ login + " Senha: "+ senha + " Estado:" +estado);

        Usuario usuario = this.usuarios.get(login);

        if (!this.contemUsuario(login)) {
            throw new UsuarioNaoCadastradoException();
        } else {
            if (!senha.equals(usuario.getSenha())){
                throw new SenhaInvalidaException("Senha inválida.");
            }
            usuario.setEstadoCivil(estado);
        }
    }

    /*
     * Metodo para edição do aniversario de um usuario, passando como parametro login, senha e a data
     * verifica se contem o usuario e se a senha é valida
     * se não for lança duas exceções
     * UsuarioNaoCadastrado e SenhaInvalida
     * Caso contrario edita o aniversario
     */
    public void editarAniversario(String login, String senha, String data) throws UsuarioNaoCadastradoException, SenhaInvalidaException {
        logger.info("Editando o aniversário do Usuario com login: "+ login + " Senha: "+ senha + " Data:" +data);

        Usuario usuario = this.usuarios.get(login);

        if (!this.contemUsuario(login)) {
            throw new UsuarioNaoCadastradoException();
        }
            if (!senha.equals(usuario.getSenha()))
                throw new SenhaInvalidaException("Senha inválida.");
        usuario.setAniversario(data);

    }

    /*
     * Metodo para edição da cidade natal de um usuario, passando como parametro login, senha e a cidade natal
     * verifica se contem o usuario e se a senha é valida
     * se não for lança duas exceções
     * UsuarioNaoCadastrado e SenhaInvalida
     * Caso contrario edita a cidade natal
     */
    public void editarCidadeNatal(String login, String senha, String cidade) throws UsuarioNaoCadastradoException, SenhaInvalidaException {
        logger.info("Editando a Cidade Natal do Usuario com login: "+ login + " Senha: "+ senha + " Cidade:" +cidade);

        Usuario usuario = this.usuarios.get(login);

        if (!this.contemUsuario(login)) {
            throw new UsuarioNaoCadastradoException();
        }
         if (!senha.equals(usuario.getSenha()))
         throw new SenhaInvalidaException("Senha inválida.");
         usuario.setCidadeNatal(cidade);

    }

    /*
     * Metodo que verifica se um usuario é amigo do outro passando o login e o amigo
     * se o amigo contiver na lista de amigos do usuarios
     * retorna verdadeiro
     * caso contrario falso!
     */
    public boolean ehAmigo(String login, String amigo){
        logger.info("Verificando se o usuario com login: "+login+" é amigo do usuario: "+amigo);

        Usuario usuario = this.usuarios.get(login);

        if(usuario.getListAmigos().contains(this.usuarios.get(amigo))){
            return true;
        }else{
            return false;
        }

    }

    /*
     * Metodo de adição de amigos, passando como parametro o login do usuario e o amigo que irá ser adicionado a lista do login passado!
     * Verifica antes se os o usuario e o amigo estao cadastrados, se não estiverem lança uma exceção: UsuarioNaoCadastrado
     * Verifica se o usuario login do usuario é igual ao do amigo, se for lança uma exceção: ContaRepetida
     * Verifica se o amigo passado ja está na lista do usuario, se estiver lança a exceção: AmigoRepetido
     * verifica se o amigo ja contem na lista do usuario que esta na lista de pendentes e adiciona apenas quando o outro tambem o adicionar!
     * Adiciona apenas se ambos estiverem na lista de pendentes um do outro!
     Caso contrario se estiver tudo OK, adiciona o usuario na lista do amigo e o amigo na lista do usuario!
     */
    public void adicionarAmigo(String id, String amigo) throws AmigoRepetidoException, UsuarioNaoCadastradoException, ContaRepetidaException {
        logger.info("Adicionando amigo com login: "+id+" ao amigo: "+amigo);

        Usuario usuario1 = this.usuarios.get(id);
        Usuario  usuario2 = this.usuarios.get(amigo);

        if(!this.contemUsuario(id) || !this.contemUsuario(amigo)){
            throw new UsuarioNaoCadastradoException();
        }
        if(id.equals(amigo)){
            throw new ContaRepetidaException("Usuário não pode adicionar a si mesmo como amigo.");
        }
        if(this.ehAmigo(id, amigo)){
            throw new AmigoRepetidoException();
        }else{
            if(usuario1.getPendentes().contains(usuario2)){
                throw new AmigoRepetidoException("Usuário já está adicionado como amigo, esperando aceitação do convite.");
            }
            usuario1.getPendentes().add(usuario2);
            if(usuario1.getPendentes().contains(usuario2) && usuario2.getPendentes().contains(usuario1)){
               usuario1.getListAmigos().add(usuario2);
               usuario2.getListAmigos().add(usuario1);
            }
        }

    }

    /*
     * Retorna a lista de amigos do usuario que contem o login passado como parametro!
     */
    public String getAmigos(String login){
       logger.info("Retornando a lista de amigos do usuario com login: "+login);
       
       return this.usuarios.get(login).getAmigos();

    }

    /*
     * Metodo de remoção de amigos, passando como parametro o login do usuario e o amigo que irá ser removido da lista do login passado!
     * Verifica antes se os o usuario e o amigo estao cadastrados, se não estiverem lança uma exceção: UsuarioNaoCadastrado
     * verifica se o amigo que for removido está na lista do usuario, senão estiver lança a exceção: UsuarioNaoCadastrado com a mensagem: "Usuários não são amigos"
     Caso contrario se estiver tudo OK, remove o usuario na lista do amigo e o amigo na lista do usuario!
     */
    public void removerAmizade(String id, String amigo) throws UsuarioNaoCadastradoException{
         logger.info("Removendo o amigo com login: "+id+" do amigo: "+amigo);

         Usuario usuario1 = this.usuarios.get(id);
         Usuario  usuario2 = this.usuarios.get(amigo);


        if(!this.contemUsuario(id) || !this.contemUsuario(amigo)){
            throw new UsuarioNaoCadastradoException();
        }
        if (!this.ehAmigo(id, amigo)){
            throw new UsuarioNaoCadastradoException("Usuários não são amigos");
        }
        usuario1.getListAmigos().remove(usuario2);
        usuario2.getListAmigos().remove(usuario1);


    }

    /*
     * Metodo que encerra O sistema!
     * Grava no arquivo todos os usuários
     * Limpa a lista de usuários
     * Ler o aqruivo.
     */

    public void encerrarSistema() throws IOException, ClassNotFoundException {

       this.p.gravaArquivo(usuarios);
       this.usuarios.clear();
       usuarios = this.p.lerArquivo();
    }

}
